package org.wjw.tcp;

import java.io.*;
import java.net.BindException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;

public class TCPEchoServer {
    //声明用于服务端的类
    private ServerSocket socket;

    //构造方法，指定端口号
    public TCPEchoServer(int port) throws IOException {
        //校验端口
        if (port < 1025 || port > 65535) {
            throw new BindException("端口号建议在1025-65535之间");
        }

        //根据指定的端口号初始化Socket服务
        this.socket = new ServerSocket(port);

    }

    //启动服务
    public void start() throws IOException {
        System.out.println("服务已启动,等待客户端连接");
        //循环接受客户端连接
        while (true) {
            //接受客户端请求
            Socket clintSocket = socket.accept();
            //接收到客户端之后，交给专门处理连接的方法
            processConnection(clintSocket);

        }
    }

    //为了方便维护，将数据处理逻辑抽取成了一个方法
    private void processConnection(Socket clintSocket) throws IOException {
        //所有的通信数据的在Socket的对象clintSocket中
        try (InputStream inputStream = clintSocket.getInputStream();
             OutputStream outputStream = clintSocket.getOutputStream()) {
            //循环处理客户端发来的数据
            while (true) {
                //Scanner来简化字符串的读取
                Scanner scanner = new Scanner(System.in);
                //判断是否还有数据
                if (!scanner.hasNextLine()) {
                    System.out.printf("[%s,%d] 客户端已下线\n", clintSocket.getInetAddress().toString(),
                            clintSocket.getPort());
                    break;
                }
                //获取用户传来的具体内容
                String request = scanner.nextLine();
                //根据请求内容计算响应
                String response = process(request);
                //把响应返回给客户端
                PrintWriter Writer = new PrintWriter(outputStream);
                //向输出流中写入响应数据
                Writer.println(response);
                //强制刷新缓冲区
                Writer.flush();
                //打印日志
                System.out.printf("[%s:%d] request = %s, response = %s\n", clintSocket.getInetAddress().toString(),
                        clintSocket.getPort(), request, response);
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        } finally {
            clintSocket.close();
        }


    }

    //处理响应
    private String process(String request) {
        return request;
    }

    public static void main(String[] args) throws IOException {
        //初始化服务器
        TCPEchoServer server = new TCPEchoServer(9090);
        //开启服务
        server.start();
    }
}
